package com.yeyks.controller;

import com.alibaba.fastjson.JSON;
import com.yeyks.dal.dao.HotelInfoMapper;
import com.yeyks.dal.dao.OrderInfoMapper;
import com.yeyks.dal.dao.ShareLogMapper;
import com.yeyks.dal.domain.AccountInfo;
import com.yeyks.dal.domain.HotelInfo;
import com.yeyks.dal.domain.OrderInfo;
import com.yeyks.exception.PermissionInvalidException;
import com.yeyks.exception.TokenInvalidException;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.OrderStatus;
import com.yeyks.model.em.AccountType;
import com.yeyks.model.em.ResponseStatus;
import com.yeyks.service.AccountService;
import com.yeyks.util.Utility;
import com.yeyks.exception.PermissionInvalidException;
import com.yeyks.exception.TokenInvalidException;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.OrderStatus;
import com.yeyks.model.em.AccountType;
import com.yeyks.model.em.ResponseStatus;
import com.yeyks.service.AccountService;
import com.yeyks.util.Utility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/ajax/stat")
public class StatisticalController {
    private static Logger logger = LoggerFactory.getLogger(StatisticalController.class);

    @Autowired
    AccountService accountService;
    @Autowired
    OrderInfoMapper orderInfoMapper;

    @Autowired
    HotelInfoMapper hotelInfoMapper;

    @Autowired
    ShareLogMapper shareLogMapper;

    /**
     * 统计订单总数据
     * @param token
     * @param hotelIds
     * @param orderStart
     * @param orderEnd
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/totalFee", method = RequestMethod.POST)
    public ResponseEntity<?> totalFee(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "hotelIds", defaultValue = "", required = true) String hotelIds,
            @RequestParam(name = "orderStart", defaultValue = "0", required = true) Long orderStart,
            @RequestParam(name = "orderEnd", defaultValue = "0", required = true) Long orderEnd
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo operatorInfo = accountService.token2AccountInfo(token);

            List<Integer> hotelIdList = null;
            if (hotelIds != null && !StringUtils.isEmpty(hotelIds)) {
                hotelIdList = Utility.str2intList(hotelIds);

            } else {
                hotelIdList = accountInfo2HotelInfoList(operatorInfo);
            }


            List<Map> orderList = orderInfoMapper.selectFromHotelMgr2(
                    hotelIdList,
                    orderStart == 0 ? null : new Date(orderStart),
                    orderEnd == 0 ? null : new Date(orderEnd));

            Integer totalFee = 0, totalTx = 0, totalRefundFee = 0, orderNum = orderList.size();
            for (Map orderInfo : orderList) {
                try {
                    String extraInfo = orderInfo.get("extra_info").toString();

                    int orderTotalFee = 0;
                    int orderRefundFee = 0;
                    Integer orderStatus = Integer.parseInt(orderInfo.get("status").toString());
                    if (orderStatus.intValue() != OrderStatus.prePay &&
                            orderStatus.intValue() != OrderStatus.payFailed) {
                        // 总金额累加
                        try {
                            orderTotalFee = Integer.parseInt(orderInfo.get("snapshot_total_fee").toString());
                        } catch (Throwable e) {
                            e.printStackTrace();
                        }

                        // 退款累加
                        if (orderStatus.intValue() == OrderStatus.postRefund) {
                            try {
                                orderRefundFee = Integer.parseInt(orderInfo.get("snapshot_refund_fee").toString());
                            } catch (Throwable e) {
                                e.printStackTrace();
                            }
                            totalRefundFee += orderRefundFee;
                            orderTotalFee -= orderRefundFee;
                        }
                    }
                    totalFee += orderTotalFee;


                    // 抽成累加
                    Map pcInfo = JSON.parseObject(Utility.getExtraInfo(extraInfo, "snapshot_pcinfo"), Map.class);
                    if (pcInfo != null) {
                        try {
                            Integer pc = null;
                            if (operatorInfo.getType() == AccountType.Administrator) {
                                pc = Integer.parseInt(pcInfo.get("admin").toString());
                            } else if (operatorInfo.getType() == AccountType.BranchManager) {
                                pc = Integer.parseInt(pcInfo.get("branch").toString());
                            } else if (operatorInfo.getType() == AccountType.CityManager) {
                                pc = Integer.parseInt(pcInfo.get("city").toString());
                            }

                            Integer parentTax = Integer.parseInt(orderInfo.get("hotel_parent_tax").toString());

                            Integer tx = pc * (orderTotalFee - orderRefundFee) * parentTax / 1000 / 1000;
                            totalTx += tx;
                        } catch (Throwable e) {
                            logger.warn("获取抽成比例失败", e);
                        }
                    }

                } catch (Throwable e) {
                    logger.warn("获取totalFee失败", e);
                }
            }

            responseBody.addMapBody("totalFee", totalFee);
            responseBody.addMapBody("totalTx", totalTx);
            responseBody.addMapBody("totalRefundFee", totalRefundFee);
            responseBody.addMapBody("orderNum", orderNum);

            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 详细统计订单额度
     * @param token
     * @param hotelIds
     * @param groupByDtFmt
     * @param orderStart
     * @param orderEnd
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/statFee", method = RequestMethod.POST)
    public ResponseEntity<?> statFee(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "hotelIds", defaultValue = "", required = true) String hotelIds,
            @RequestParam(name = "groupByDtFmt", defaultValue = "", required = true) String groupByDtFmt,
            @RequestParam(name = "orderStart", defaultValue = "", required = true) Long orderStart,
            @RequestParam(name = "orderEnd", defaultValue = "", required = true) Long orderEnd
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo operatorInfo = accountService.token2AccountInfo(token);

            List<Integer> hotelIdList = null;
            if (hotelIds != null && !StringUtils.isEmpty(hotelIds)) {
                hotelIdList = Utility.str2intList(hotelIds);

            } else {
                hotelIdList = accountInfo2HotelInfoList(operatorInfo);
            }

            groupByDtFmt = URLDecoder.decode(groupByDtFmt);

            List<Map> feeInfos = orderInfoMapper.select4Stat(
                    hotelIdList, groupByDtFmt,
                    orderStart == null ? null : new Date(orderStart),
                    orderEnd == null ? null : new Date(orderEnd));

            responseBody.setBody(feeInfos);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    List<Integer> accountInfo2HotelInfoList(AccountInfo operatorInfo) throws Exception {

        List<Integer> hotelIdList = null;
        if (operatorInfo.getType() == AccountType.HotelManager) {
            List<HotelInfo> hotelInfoList = accountService.searchHotelsByOperator(operatorInfo.getId());
            if (hotelInfoList != null && hotelInfoList.size() != 0) {
                hotelIdList = new ArrayList<>();
                for (HotelInfo hotelInfo : hotelInfoList) {
                    hotelIdList.add(hotelInfo.getId());
                }
            }
        } else if (operatorInfo.getType() == AccountType.CityManager) {
            List<HotelInfo> hotelInfoList = accountService.searchHotelsByAdministrator(operatorInfo.getId());
            if (hotelInfoList != null && hotelInfoList.size() != 0) {
                hotelIdList = new ArrayList<>();
                for (HotelInfo hotelInfo : hotelInfoList) {
                    hotelIdList.add(hotelInfo.getId());
                }
            }
        } else if (operatorInfo.getType() == AccountType.CityAgent) {
            //查出所有的城市运营商
            List<AccountInfo> cityAccountInfos = accountService.getChildAccounts(operatorInfo.getId());
            List<Integer> ids = new ArrayList<>();
            for (AccountInfo accountInfo : cityAccountInfos) {
                ids.add(accountInfo.getId());
            }

            List<HotelInfo> hotelInfoList = accountService.searchHotelsByAdministrator(ids);
            if (hotelInfoList != null && hotelInfoList.size() != 0) {
                hotelIdList = new ArrayList<>();
                for (HotelInfo hotelInfo : hotelInfoList) {
                    hotelIdList.add(hotelInfo.getId());
                }
            }
        } else if (operatorInfo.getType() == AccountType.BranchManager) {
            //查出省
            List<AccountInfo> cityAccountInfos = accountService.getChildAccounts(operatorInfo.getId());
            List<Integer> ids = new ArrayList<>();
            for (AccountInfo accountInfo : cityAccountInfos) {
                ids.add(accountInfo.getId());
            }
            //查出市
            List<AccountInfo> cityAccountInfos2 = accountService.getChildAccountsV2(ids);
            List<Integer> ids2 = new ArrayList<>();
            for (AccountInfo accountInfo : cityAccountInfos2) {
                ids2.add(accountInfo.getId());
            }
            List<HotelInfo> hotelInfoList = accountService.searchHotelsByAdministrator(ids2);
            if (hotelInfoList != null && hotelInfoList.size() != 0) {
                hotelIdList = new ArrayList<>();
                for (HotelInfo hotelInfo : hotelInfoList) {
                    hotelIdList.add(hotelInfo.getId());
                }
            }
        } else if (operatorInfo.getType() == AccountType.Administrator) {
            hotelIdList = null;
        } else {
            throw new PermissionInvalidException();
        }

        return hotelIdList;
    }

    /**
     * 查询有效订单的酒店的房间个数
     * @param token
     * @param hotelIds
     * @param orderStart
     * @param orderEnd
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/hotelTopList", method = RequestMethod.POST)
    public ResponseEntity<?> hotelTopList(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "hotelIds", defaultValue = "", required = true) String hotelIds,
            @RequestParam(name = "orderStart", defaultValue = "0", required = true) Long orderStart,
            @RequestParam(name = "orderEnd", defaultValue = "0", required = true) Long orderEnd
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo operatorInfo = accountService.token2AccountInfo(token);

            List<Integer> hotelIdList = null;
            if (hotelIds != null && !StringUtils.isEmpty(hotelIds)) {
                hotelIdList = Utility.str2intList(hotelIds);

            } else {
                hotelIdList = accountInfo2HotelInfoList(operatorInfo);
            }

            List<Map> hotelTopList = orderInfoMapper.selectHotelOrderTopList(hotelIdList,
                    orderStart == 0 ? null : new Date(orderStart),
                    orderEnd == 0 ? null : new Date(orderEnd));

            responseBody.setBody(hotelTopList);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    @ApiIgnore
    @RequestMapping(value = "/hotelFeeTopList", method = RequestMethod.POST)
    public ResponseEntity<?> hotelFeeTopList(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "hotelIds", defaultValue = "", required = true) String hotelIds,
            @RequestParam(name = "orderStart", defaultValue = "0", required = true) Long orderStart,
            @RequestParam(name = "orderEnd", defaultValue = "0", required = true) Long orderEnd
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo operatorInfo = accountService.token2AccountInfo(token);

            List<Integer> hotelIdList = null;
            if (hotelIds != null && !StringUtils.isEmpty(hotelIds)) {
                hotelIdList = Utility.str2intList(hotelIds);

            } else {
                hotelIdList = accountInfo2HotelInfoList(operatorInfo);
            }

            List<Map> hotelTopList = orderInfoMapper.selectHotelOrderTopList(hotelIdList,
                    orderStart == 0 ? null : new Date(orderStart),
                    orderEnd == 0 ? null : new Date(orderEnd));

            responseBody.setBody(hotelTopList);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    @ApiIgnore
    @RequestMapping(value = "/shareGroupList", method = RequestMethod.POST)
    public ResponseEntity<?> shareGroupList(
            @RequestParam(name = "gmtStart", defaultValue = "0", required = true) Long gmtStart,
            @RequestParam(name = "gmtEnd", defaultValue = "0", required = true) Long gmtEnd
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            List<Map> shareCountGroupList = shareLogMapper.countGroupByDay(
                    gmtStart == 0 ? null : new Date(gmtStart),
                    gmtEnd == 0 ? null : new Date(gmtEnd));

            responseBody.setBody(shareCountGroupList);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 根据账号id统计该账号下代理商的酒店数量信息
     * @param branchId
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/getHotelEnrollTopList", method = RequestMethod.POST)
    public ResponseEntity<?> getHotelEnrollTopList(
            @RequestParam(name = "branchId", defaultValue = "", required = true) Integer branchId
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            List<Map> topList = null;
            if (branchId == null || branchId == 0) {
                topList = hotelInfoMapper.countGroupByBranch();

            } else {
                topList = hotelInfoMapper.countGroupByCityMgr(branchId);
            }

            responseBody.setBody(topList);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }
}
